package com.jvnsrp.mirror;

import com.jcraft.jsch.*;

import java.util.Properties;

/**
 * @author Jevon
 * @version V1.0
 * @date 2021/7/11 14:26
 **/
public class SftpUtils {
    private Session session = null;
    private ChannelSftp channel = null;

    public SftpUtils(String host,int port,String username,String password, int timeout) throws JSchException {
        // 创建JSch对象
        JSch jsch = new JSch();
        // 根据用户名，主机ip，端口获取一个Session对象
        session = jsch.getSession(username, host, port);
        // 设置密码
        session.setPassword(password);
        Properties config = new Properties();
        // 首次登陆远程的时候提示Are you sure you want to continue connecting (yes/no)。这时用sshpass会不好使。
        config.put("StrictHostKeyChecking", "no");
        // 为Session对象设置properties
        session.setConfig(config);
        // 设置timeout时间
        session.setTimeout(timeout);
        // 通过Session建立链接
        session.connect();
        System.out.println("Session connected.");
        // 打开SFTP通道
        channel = (ChannelSftp)session.openChannel("sftp");
        // 建立SFTP通道的连接
        channel.connect();
        System.out.println("Channel connected.");
    }

    /**
     * 检查路径 若无路径则创建
     * @param path
     * @throws SftpException
     */
    private  void checkPath(String path) throws SftpException {
        // 获取文件父目录
        int i = path.lastIndexOf("/");
        if(i != -1){
            String p = path.substring(0, i);
            try {
                if (channel.ls(p) == null) {
                    channel.mkdir(p);
                }
            }catch (SftpException e){
                channel.mkdir(p);
            }
        }
    }

    /**
     * 上传文件
     */
    public void put(String source, String target) {
        try {
            checkPath(target);
            channel.put(source, target);
            System.out.println("[put-success]:" + source);
        } catch (SftpException e) {
            System.out.println("[put-fail]:" + source);
        }
    }

    /**
     * 下载文件
     */
    public void get(String source, String target) {
        try {
            channel.get(source, target);
            System.out.println("[get-success]:" + source);
        } catch (SftpException e) {
            System.out.println("[get-fail]:" + source);
        }
    }

    /**
     * 切换目录文件
     */
    public void cd(String path) {
        try {
            channel.cd(path);
            System.out.println("[cd-success]:" + path);
        } catch (SftpException e) {
            System.out.println("[cd-fail]:" + path);
        }
    }

    /**
     * 删除文件
     */
    public void rm(String path) {
        try {
            channel.rm(path);
            System.out.println("[rm-success]:" + path);
        } catch (SftpException e) {
            System.out.println("[rm-fail]:" + path);
        }
    }

    /**
     * 删除文件夹
     */
    public void rmdir(String path) {
        String cmd = "rm -rf " + path;
        try {
            runCmd(cmd);
            System.out.println("[rm-success]:" + path);
        } catch (JSchException e) {
            System.out.println("[rm-fail]:" + path);
        }
    }

    /**
     * 执行命令
     * @param cmd
     * @throws JSchException
     */
    private void runCmd(String cmd) throws JSchException {
        ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
        channelExec.setCommand(cmd);
        channelExec.setInputStream(null);
        channelExec.setErrStream(System.err);
        channelExec.connect();
        while(true){
            if(channelExec.getExitStatus() == 0){
                break;
            }
            try{
                Thread.sleep(500);
            }catch(Exception ee){
                ee.printStackTrace();
            }
        }
        channelExec.disconnect();
    }

    /**
     * 计算目录下所有文件的md5值 写入md5file文件
     * @param dir
     * @param md5file
     */
    public void md5sum(String dir, String md5file){
        String cmd = "cd "+dir+";find ./ -type f -print0| xargs -0 md5sum > " + md5file;
        try {
            checkPath(md5file);
            runCmd(cmd);
            System.out.println("[md5sum-success]:" + dir);
        } catch (JSchException | SftpException e) {
            System.out.println("[md5sum-fail]:" + dir);
        }
    }

    /**
     * 关闭链接
     */
    public void close() {
        if (channel != null) {
            channel.disconnect();
            System.out.println("Channel disconnected.");
        }
        if (session != null) {
            session.disconnect();
            System.out.println("Session disconnected.");
        }
    }

    public void mirrorFull(String source,String target){
        rmdir(target);
        put(source, target);
    }

    public void mirrorTime(String source,String target){
        rmdir(target);
        put(source, target);
    }
}